package org.hikari.qqbot.xiuxian.task;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hikari.qqbot.xiuxian.service.bo.SystemSetting;
import org.hikari.qqbot.xiuxian.util.MessageUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.LockSupport;

/**
 * created at 2024-12-19 18:29:47
 *
 * @author yinchao
 * @version 1.0
 **/
@Slf4j
@RequiredArgsConstructor
public class TimedTaskHealthChecker {

    private volatile boolean running = false;

    private final List<UserTaskRuntime> checkList = new ArrayList<>();

    private final SystemSetting setting;

    public void start() {
        if (running) {
            return;
        }
        synchronized (this) {
            if (running) {
                return;
            }
        }
        this.running = true;
        new Thread(this::check, "TimedTaskHealthChecker").start();
    }

    public void stop() {
        if (!running) {
            return;
        }
        synchronized (this) {
            if (!running) {
                return;
            }
        }
        this.running = false;
    }

    public void addRuntimeToCheckList(UserTaskRuntime runtime) {
        synchronized (this.checkList) {
            boolean exists = checkList.stream()
                    .anyMatch(exist -> Objects.equals(exist.getUserSetting().getUserId(), runtime.getUserSetting().getUserId()));
            if (exists) {
                return;
            }
            this.checkList.add(runtime);
        }
    }

    public void check() {
        while (running) {
            LockSupport.parkNanos((long) setting.getTaskHealthCheckIntervalSeconds() * 1000000000);

            List<UserTaskRuntime> runtimeList = checkList;

            long begin = System.currentTimeMillis();
            log.info("开始检查用户任务健康状况. 总共有{}个用户", runtimeList.size());
            int i = 0;
            int size = runtimeList.size();
            int goodCount = 0;
            int badCount = 0;
            for (UserTaskRuntime runtime : runtimeList) {
                try {
                    runtime.checkTaskHealth();
                    goodCount++;
                    log.info("({}/{}) 用户({})健康检查完成", ++i, size, runtime.getUserSetting().getUserId());
                } catch (Throwable e) {
                    badCount++;
                    log.error("({}/{}) 用户({})健康检查异常", ++i, size, runtime.getUserSetting().getUserId(), e);
                }
            }

            Date nextTime = new Date(System.currentTimeMillis() + setting.getTaskHealthCheckIntervalSeconds() * 1000L);
            log.info("所有用户健康检查完成, 总耗时: {}ms. 成功数量: {} 失败数量: {} 预计下次检查时间: {}", System.currentTimeMillis() - begin, goodCount, badCount, MessageUtil.getDisplaySendTime(nextTime));
        }
    }

}
